﻿#ifndef __SBTPL_H__
#define __SBTPL_H__

#if _MSC_VER
#pragma once
#pragma warning(push)
#pragma warning(disable:4127)	// L4, conditional expression is constant
#pragma warning(disable:4624)	// L1, cannot create destructor
#endif

#ifdef __cplusplus

#include "sbcs.h"
#include <new>
#include <functional>

//////////////////////////////////////////////////////////////////////////
// tpl the templates





















//////////////////////////////////////////////////////////////////////////
// class definition
#if _SB_CPP11_CLS_
#define KCS_DELETE						= delete
#define KCS_DEFAULT						= default
#else
#define KCS_DELETE
#define KCS_DEFAULT
#endif

//
#define KCH_NOCTOR(cls)					private: cls() KCS_DELETE
#define KCH_NODTOR(cls)					private: ~cls() KCS_DELETE
#define KCH_NOCOPY(cls)					private: cls(const cls&) KCS_DELETE; cls& operator=(cls const&) KCS_DELETE
#define KCH_NOEQ(cls)					private: void operator==(cls const&) const KCS_DELETE; void operator !=(cls const&) const KCS_DELETE
#define KCH_NOEC(cls)					KCH_NOEQ(cls); KCH_NOCOPY(cls)

#define KCH_SELF(cls)					public: typedef cls this_type
#define KCH_SUPER(cls)					public: typedef cls super_type

#define KCH_DERIVE(cls,spr)				KCH_SELF(cls); KCH_SUPER(spr)
#define KCH_BASE(cls,spr)				KCH_DERIVE(cls,spr); KCH_NOCOPY(cls); KCH_NOEQ(cls)
#define KCH_SEAL(cls)					KCH_NOCTOR(cls); KCH_NOCOPY(cls); KCH_NOEQ(cls)

#define KCH_FRIEND(cls)					friend class cls
#define KCH_INTERN(cls)					public: class cls

#define KCH_OPNEW(cls)					public: void* operator new(size_t size) { return k_new(size, kbyte); }; void operator delete(void* ptr) { k_delete(ptr); }
#define KCH_OPNEWVEC(cls)				public: void* operator new[](size_t size) { return k_new(size, kbyte); }; void operator delete[](void* ptr) { k_delete(ptr); }
#define KCH_OPNEWREPLACE(cls)			public: void* operator new(size_t, void* ptr) { return ptr; }; void operator delete(void*, void*) {}

#if __GNUC__ || _SB_PPC_
#define KCH_AVOID_FOR_INTERFACE(cls)	virtual ~cls() {}
#else
#define KCH_AVOID_FOR_INTERFACE(cls)	~cls() {}
#endif

namespace tpl
{
	/** no copy class. */
	class NoCopyClass
	{
	protected:
		NoCopyClass() {}
		~NoCopyClass() {}

	private:
		NoCopyClass(NoCopyClass const&) KCS_DELETE;
#if _SB_CPP11_MOVE_
		NoCopyClass(NoCopyClass&&) KCS_DELETE;
#endif
		const NoCopyClass& operator=(NoCopyClass const&)KCS_DELETE;
	};

	/** sealed class. */
	class SealClass
	{
	protected:
		SealClass() KCS_DELETE;
		~SealClass() KCS_DELETE;

	private:
		SealClass(SealClass const&) KCS_DELETE;
#if _SB_CPP11_MOVE_
		SealClass(SealClass&&) KCS_DELETE;
#endif
		const SealClass& operator=(SealClass const&)KCS_DELETE;

		void operator==(SealClass const&) const KCS_DELETE;
		void operator!=(SealClass const&) const KCS_DELETE;
	};
}























//////////////////////////////////////////////////////////////////////////
// type classes
namespace tpl
{
	// type trait
	namespace TypeTrait
	{
		// test float
		template <typename T> struct IsFloat { enum { value = false }; };
		template <> struct IsFloat < float > { enum { value = true }; };
		template <> struct IsFloat < double > { enum { value = true }; };
		template <> struct IsFloat < long double > { enum { value = true }; };

		// test integral
		template <typename T> struct IsInt { enum { value = false }; };
		template <> struct IsInt < ksbyte > { enum { value = true }; };
		template <> struct IsInt < kshort > { enum { value = true }; };
		template <> struct IsInt < kint > { enum { value = true }; };
		template <> struct IsInt < klong > { enum { value = true }; };
		template <> struct IsInt < kbyte > { enum { value = true }; };
		template <> struct IsInt < kushort > { enum { value = true }; };
		template <> struct IsInt < kuint > { enum { value = true }; };
		template <> struct IsInt < kulong > { enum { value = true }; };
		template <> struct IsInt < bool > { enum { value = true }; };
		template <> struct IsInt < kchar > { enum { value = true }; };
		template <> struct IsInt < kwchar > { enum { value = true }; };

		// test signed integral
		template <typename T> struct IsSint { enum { value = false }; };
		template <> struct IsSint < ksbyte > { enum { value = true }; };
		template <> struct IsSint < kshort > { enum { value = true }; };
		template <> struct IsSint < kint > { enum { value = true }; };
		template <> struct IsSint < klong > { enum { value = true }; };

		// test unsigned integral
		template <typename T> struct IsUint { enum { value = false }; };
		template <> struct IsUint < kbyte > { enum { value = true }; };
		template <> struct IsUint < kushort > { enum { value = true }; };
		template <> struct IsUint < kuint > { enum { value = true }; };
		template <> struct IsUint < kulong > { enum { value = true }; };
		template <> struct IsUint < kvshort > { enum { value = true }; };
		template <> struct IsUint < kvint > { enum { value = true }; };
		template <> struct IsUint < kvlong > { enum { value = true }; };

		// test arithmetic
		template <typename T> struct IsArithmetic { enum { value = IsFloat<T>::value || IsInt<T>::value }; };

		// test void
		template <typename T> struct IsVoid { enum { value = false }; };
		template <> struct IsVoid < void > { enum { value = true }; };
		template <> struct IsVoid < void const > { enum { value = true }; };
		template <> struct IsVoid < void volatile > { enum { value = true }; };
		template <> struct IsVoid < void const volatile > { enum { value = true }; };

		// test char
		template <typename T> struct IsChar { enum { value = false }; };
		template <> struct IsChar < char > { enum { value = true }; };
		template <> struct IsChar < kwchar > { enum { value = true }; };
#if !_SB_WINDOWS_
		template <> struct IsChar<kucs2char> { enum { value = true }; };
#endif
#if _SB_WINDOWS_
		template <> struct IsChar < kucs4char > { enum { value = true }; };
#endif

		// test pointer
		template <typename T> struct IsPtr { enum { value = false }; };
		template <typename T> struct IsPtr < T* > { enum { value = true }; };
		template <typename T> struct IsPtr < const T* > { enum { value = true }; };
		template <typename T> struct IsPtr < const T* const > { enum { value = true }; };
		template <typename T> struct IsPtr < volatile T* > { enum { value = true }; };
		template <typename T> struct IsPtr < volatile T* const > { enum { value = true }; };

		// test funcdamental
		template <typename T> struct IsFundamental { enum { value = IsArithmetic<T>::value || IsVoid<T>::value }; };

		// test POD
		template <typename T> struct IsPOD { enum { value = __is_pod(T) || __is_enum(T) || IsArithmetic<T>::value || IsPtr<T>::value }; };

		// test equal type
		template <typename A, typename B> struct IsEqual { enum { value = false }; };
		template <typename A> struct IsEqual < A, A > { enum { value = true }; };

		// test array
		template <typename T> struct IsArray { enum { value = false }; };
		template <typename T, ksize_t N> struct IsArray < T[N] > { enum { value = true }; };

		// remove const
		template <typename T> struct RemoveConst { typedef T type; };
		template <typename T> struct RemoveConst < const T > { typedef T type; };

		// remove reference
		template <typename T> struct RemoveRef { typedef T type; };
		template <typename T> struct RemoveRef < T& > { typedef T type; };
#if _SB_CPP11_MOVE_
		template <typename T> struct RemoveRef < T&& > { typedef T type; };
#endif

		// movable
		template <typename T, typename U> struct MovableBase { typedef U copy_type; };
#if _SB_CPP11_MOVE_
		template <typename T> struct MovableBase < T, const T& > { typedef const T& copy_type; typedef T&& move_type; };
#else
		template <typename T> struct MovableBase<T, const T&> { typedef const T& copy_type; };
#endif

		// right-value to left-vaue
		template <typename T> struct RvalueToLvalueRef { typedef T type; };
#if _SB_CPP11_MOVE_
		template <typename T> struct RvalueToLvalueRef < T&& > { typedef T& type; };
#endif

		// copy qualifier
		template <typename F, typename T> struct CopyQualifier { typedef T type; };
		template <typename F, typename T> struct CopyQualifier < const F, T > { typedef const T type; };
		template <typename F, typename T> struct CopyQualifier < volatile F, T > { typedef volatile T type; };
		template <typename F, typename T> struct CopyQualifier < const volatile F, T > { typedef const volatile T type; };
	}

	// call trait
	namespace CallTrait
	{
		template <typename T, bool B>
		struct ParamType
		{
			typedef const T& param_type;
			typedef const T& const_param_type;
		};

		template <typename T>
		struct ParamType < T, true >
		{
			typedef const T param_type;
			typedef const T const_param_type;
		};

		template <typename T>
		struct ParamType < T*, true >
		{
			typedef T* param_type;
			typedef const T* const_param_type;
		};

		template <typename T>
		struct CallTypeBase
		{
			enum { value = TypeTrait::IsArithmetic<T>::value || TypeTrait::IsPtr<T>::value || (sizeof(T) <= sizeof(void*) && TypeTrait::IsPOD<T>::value) };
			typedef T value_type;
			typedef T& reference_type;
			typedef const T& const_reference_type;
			typedef typename ParamType<T, value>::param_type param_type;
			typedef typename ParamType<T, value>::const_param_type const_param_type;
		};

		template <typename T>
		struct CallType : public CallTypeBase < T > {};

		template <typename T>
		struct CallType < T& >
		{
			typedef T value_type;
			typedef T& reference_type;
			typedef const T& const_reference_type;
			typedef T& param_type;
			typedef T& const_param_type;
		};

		template <typename T, ksize_t N>
		struct CallType < T[N] >
		{
			typedef T array_type[N];
			typedef const T* value_type;
			typedef array_type& reference_type;
			typedef const array_type& const_reference_type;
			typedef const T& param_type;
			typedef const T& const_param_type;
		};

		template <typename T, ksize_t N>
		struct CallType < const T[N] >
		{
			typedef const T array_type[N];
			typedef const T* value_type;
			typedef array_type& reference_type;
			typedef const array_type& const_reference_type;
			typedef const T& param_type;
			typedef const T& const_param_type;
		};
	}

	// type trait, continue
	namespace TypeTrait
	{
		// movable
		template <typename T> struct Movable : MovableBase < T, typename CallTrait::CallType<T>::param_type > {};
	}
}























//////////////////////////////////////////////////////////////////////////
// memory classes
namespace tpl
{
	// memory trait
	namespace MemTrait
	{
		template <typename T>
		static void Construct(T* p)
		{
			::new (p)T();
		}

		template <typename T>
		static void Construct(T* p, const T& value)
		{
			::new (p)T(value);
		}

#if _SB_CPP11_MOVE_
		template <typename T>
		static void Construct(T* p, const T&& value)
		{
			::new (p)T(value);
		}
#endif

		template <typename T, typename ITER>
		static void Construct(T* p, ITER begin, ITER end)
		{
			for (ITER it = begin; it != end; ++it)
			{
				::new (p)T(*it);
				p++;
			}
		}

		template <typename T>
		static void ConstructN(T* p, ksize_t count)
		{
			for (ksize_t i = 0; i < count; i++)
#if _MSC_VER && _MSC_VER < 1800
				::new (p + i) T;
#else
				::new (p + i) T();
#endif
		}

		template <typename T>
		static void ConstructN(T* p, ksize_t count, const T& value)
		{
			for (ksize_t i = 0; i < count; i++)
				::new (p + i) T(value);
		}

		template <typename T>
		static void ConstructR(T* p, ksize_t start, ksize_t end)
		{
			for (ksize_t i = start; i < end; i++)
#if _MSC_VER && _MSC_VER < 1800
				::new (p + i) T;
#else
				::new (p + i) T();
#endif
		}

		template <typename T>
		static void ConstructR(T* p, ksize_t start, ksize_t end, const T& value)
		{
			for (ksize_t i = start; i < end; i++)
				::new (p + i) T(value);
		}

		template <typename T>
		static void ConstructF(T* begin, T* end, const T& value)
		{
			for (T* p = begin; p != end; ++p)
				::new (p)T(value);
		}

		template <typename T>
		static void Destruct(T* p)
		{
			p->~T();
			K_NOUSE(p);
		}

		template <typename T>
		static void Destruct(T* begin, T* end)
		{
			for (T* p = begin; p != end; ++p)
				p->~T();
		}

		template <typename T>
		static void DestructN(T* p, ksize_t count)
		{
			for (ksize_t i = 0; i < count; i++)
				p[i].~T();
			K_NOUSE(p);
		}

		template <typename T>
		static void DestructR(T* p, ksize_t start, ksize_t end)
		{
			for (ksize_t i = start; i < end; i++)
				p[i].~T();
			K_NOUSE(p);
		}

		template <typename T>
		static void Reconstruct(T* p)
		{
			p->~T();
			::new (p)T();
		}

		template <typename T>
		static void Reconstruct(T* p, const T& value)
		{
			p->~T();
			::new (p)T(value);
		}
	};

	/** 메모리 할당. */
	template <bool ALLOCZERO = false>
	class MemAlloc
	{
	protected:
		MemAlloc() {}
		~MemAlloc() {}

	private:
		enum { MemAllocZero = ALLOCZERO };

	public:
		void* operator new(size_t size, const char* file, int line)
		{
			return MemAllocZero ? k_alloc_dbg(size, file, line) : k_allocf_dbg(size, file, line);
		}


		void* operator new(size_t size)
		{
			return MemAllocZero ? k_alloc(size) : k_allocf(size);
		}

		void* operator new(size_t /*size*/, void* ptr)
		{
			return ptr; 
		}

		void* operator new[](size_t size, const char* file, int line)
		{
			return MemAllocZero ? k_alloc_dbg(size, file, line) : k_allocf_dbg(size, file, line);
		}

		void* operator new[](size_t size) 
		{
			return MemAllocZero ? k_alloc(size) : k_allocf(size);
		}

		void operator delete(void* ptr, const char*, int) 
		{ 
			k_free(ptr); 
		}

		void operator delete(void* ptr) 
		{
			k_free(ptr);
		}

		void operator delete(void* /*ptr*/, void* /*ptr*/)
		{
		}

		void operator delete[](void* ptr, const char*, int) 
		{
			k_free(ptr);
		}

		void operator delete[](void* ptr) 
		{
			k_free(ptr);
		}			
	};

	/** C++ STL 컨테이너용 메모리 할당. */
	template <typename T>
	class MemStlAlloc
	{
	public:
		typedef T value_type;
		typedef value_type* pointer;
		typedef const value_type* const_pointer;
		typedef value_type& reference;
		typedef const value_type& const_reference;
		typedef std::size_t size_type;
		typedef std::ptrdiff_t difference_type;

		template <typename U>
		struct rebind
		{
			typedef MemStlAlloc<U> other;
		};

		MemStlAlloc() {}
		MemStlAlloc(const MemStlAlloc&) {}
		template <typename U> MemStlAlloc(const MemStlAlloc<U>&) {}
		~MemStlAlloc() {}

		pointer address(reference v) const
		{
			return &v;
		}

		const_pointer address(const_reference v) const
		{
			return &v;
		}

		//pointer allocate(size_type n, typename std::allocator<void>::const_pointer* dummy = NULL)
		pointer allocate(size_type n, const void* dummy = NULL)
		{
			K_NOUSE(dummy);
			void* ptr = k_new(n, T);
			return (pointer)ptr; // no std::bad_alloc() 
		}

		void deallocate(pointer ptr, size_type)
		{
			k_delete((void*)ptr);
		}

		void construct(pointer ptr)
		{
			::new (static_cast<void*>(ptr)) value_type();
		}

		void construct(pointer ptr, const_reference x)
		{
			::new (static_cast<void*>(ptr)) value_type(x);
		}

		void destroy(pointer ptr)
		{
			K_NOUSE(ptr);
			ptr->~value_type();
		}

		size_type max_size() const
		{
			return static_cast<size_type>(-1) / sizeof(T);
		}

	private:
		void operator=(const MemStlAlloc&);
	};

	template <typename T>
	inline bool operator==(const MemStlAlloc<T>&, const MemStlAlloc<T>&)
	{
		return true;
	}

	template <typename T>
	inline bool operator!=(const MemStlAlloc<T>&, const MemStlAlloc<T>&)
	{
		return false;
	}
}	// tpl




















//////////////////////////////////////////////////////////////////////////
// sort
namespace tpl
{
	namespace _sort
	{
		// heap sink
		template <typename T>
		inline void HeapSink(T* data, ksize_t index, ksize_t count)
		{
			while ((index << 1) < count)
			{
				ksize_t n = index << 1;

				if ((n + 1) < count && data[n] < data[n + 1])
					n++;	// take left

				if (!(data[index] < data[n]))
					return;
				else
				{
					Swap(data[n], data[index]);
					index = n;
				}
			}
		}

		// heap sink, with pred
		template <typename T, typename FN>
		inline void HeapSink(T* data, ksize_t index, ksize_t count, FN pred)
		{
			while ((index << 1) < count)
			{
				ksize_t n = index << 1;

				if ((n + 1) < count && pred(data[n], data[n + 1]))
					n++;

				if (!pred(data[index], data[n]))
					return;
				else
				{
					Swap(data[n], data[index]);
					index = n;
				}
			}
		}

		// quick sink
		template <typename T>
		inline void QuickSink(T* data, kssize_t left, kssize_t right)
		{
			kssize_t l = left, r = right, p = left;

			do
			{
				while (data[l] < data[p])
					++l;
				while (data[p] < data[r])
					--r;

				if (l <= r)
					Swap(data[l++], data[r--]);
			} while (l < r);

			if (left < r)
				QuickSink(data, left, r);

			if (right > l)
				QuickSink(data, l, right);
		}

		// quick sink, with pred
		template <typename T, typename FN>
		inline void QuickSink(T* data, kssize_t left, kssize_t right, FN pred)
		{
			kssize_t l = left, r = right, p = left;

			do
			{
				while (pred(data[l], data[p]))
					++l;
				while (pred(data[p], data[r]))
					--r;

				if (l <= r)
					Swap(data[l++], data[r--]);
			} while (l < r);

			if (left < r)
				QuickSink(data, left, r, pred);

			if (right > l)
				QuickSink(data, l, right, pred);
		}
	}

	// heap sort
	template <typename T>
	inline void HeapSort(T* data, ksize_t size)
	{
		T* heap = data - 1;
		ksize_t count = size + 2;

		for (kssize_t i = (((kssize_t)size - 1) / 2); i >= 0; --i)
			_sort::HeapSink(heap, i + 1, count - 1);

		for (kssize_t i = (kssize_t)size - 1; i >= 0; --i)
		{
			Swap(data[0], data[i]);
			_sort::HeapSink(heap, 1, i + 1);
		}
	}

	// heap sort
	template <typename T, typename FN>
	inline void HeapSort(T* data, ksize_t size, FN pred)
	{
		T* heap = data - 1;
		ksize_t count = size + 2;

		for (kssize_t i = (((kssize_t)size - 1) / 2); i >= 0; --i)
			_sort::HeapSink(heap, i + 1, count - 1, pred);

		for (kssize_t i = (kssize_t)size - 1; i >= 0; --i)
		{
			Swap(data[0], data[i]);
			_sort::HeapSink(heap, 1, i + 1, pred);
		}
	}

	// quick sort
	template <typename T>
	inline void QuickSort(T* data, ksize_t size)
	{
		_sort::QuickSink(data, 0, (kssize_t)size - 1);
	}

	// quick sort
	template <typename T, typename FN>
	inline void QuickSort(T* data, ksize_t size, FN pred)
	{
		_sort::QuickSink(data, 0, (kssize_t)size - 1, pred);
	}
}




















//////////////////////////////////////////////////////////////////////////
// utility class
namespace tpl
{
	/** anycallback. */
	class AnyCallback : public kanycb
	{
	public:
		AnyCallback(kfunc func, kpointer data = NULL)
		{
			this->func = func;
			this->data = data;
		}

		AnyCallback& operator=(const AnyCallback& right)
		{
			this->func = right.func;
			this->data = right.data;
			return *this;
		}

		bool operator==(const AnyCallback& right)
		{
			return this->func == right.func && this->data == right.data;
		}

		bool operator!=(const AnyCallback& right)
		{
			return this->func != right.func || this->data != right.data;
		}
	};

	/** lock guard = std::lock_guard */
	template <typename T>
	class LockGuard : public T::ScopedLock
	{
		typedef LockGuard<T> this_type;
		typedef typename T::ScopedLock super_type;

	public:
		LockGuard(T& l)
			: super_type(l)
		{
		}

		operator bool()
		{
			return false;
		}
	};

	/** lock guard for pointer */
	template <typename T>
	class LockPtrGuard : public T::ScopedLock
	{
		typedef LockPtrGuard<T> this_type;
		typedef typename T::ScopedLock super_type;

	public:
		LockPtrGuard(T* l)
			: super_type(l)
		{
		}

		operator bool()
		{
			return false;
		}
	};
}






















//////////////////////////////////////////////////////////////////////////
// ptr traits
namespace tpl
{
	/** BASE 타입 포인터 LOAD & UNLOAD. */
	template <typename BASETYPE>
	class BasePtr
	{
	private:
		BASETYPE* _ptr;

	public:
		K_NOTHROW BasePtr() : _ptr(NULL)
		{
		}

		K_NOTHROW BasePtr(BASETYPE* ptr, bool isload = true)
			: _ptr(ptr)
		{
			if (ptr && isload)
				ptr->Load();
		}

		K_NOTHROW BasePtr(const BasePtr& o)
			: _ptr(o._ptr)
		{
			if (_ptr)
				_ptr->Load();
		}

		template <typename EITHERTYPE>
		K_NOTHROW BasePtr(const BasePtr<EITHERTYPE>& o)
			: _ptr(o._ptr)
		{
			if (_ptr)
				_ptr->Load();
		}

		K_NOTHROW ~BasePtr()
		{
			if (_ptr)
			{
				_ptr->Unload();
				k_test(_ptr = NULL);
			}
		}

		K_NOTHROW BasePtr& operator=(BASETYPE* right)
		{
			BASETYPE* prev = _ptr;
			_ptr = right;
			if (_ptr)
				_ptr->Load();
			if (prev)
				prev->Unload();
			return *this;
		}

		K_NOTHROW BasePtr& operator=(const BasePtr& right)
		{
			return *this = right._ptr;
		}

		template <typename EITHERTYPE>
		K_NOTHROW BasePtr& operator=(const BasePtr<EITHERTYPE>& right)
		{
			return *this = right._ptr;
		}

		template <typename EITHERTYPE>
		K_NOTHROW bool operator==(const BasePtr<EITHERTYPE>& right)
		{
			return _ptr == right._ptr;
		}

		K_NOTHROW BASETYPE* operator->() const
		{
			return _ptr;
		}

		K_NOTHROW operator BASETYPE*() const
		{
			return _ptr;
		}

		K_NOTHROW BASETYPE& operator*() const
		{
			return *_ptr;
		}

		K_NOTHROW BASETYPE** operator&()
		{
			return &_ptr;
		}

		K_NOTHROW bool operator!() const
		{
			return !_ptr;
		}

		K_NOTHROW operator bool() const
		{
			return _ptr != NULL;
		}

		K_NOTHROW BASETYPE** InitPtr()
		{
			*this = NULL;
			return &_ptr;
		}

		K_NOTHROW void InitPtr(BASETYPE* ptr)
		{
			*this = NULL;
			_ptr = ptr;
		}

		K_NOTHROW BASETYPE* Ptr() const
		{
			return _ptr;
		}

		K_NOTHROW friend bool TestPtr(const BasePtr& ptr)
		{
			return ptr._ptr != NULL;
		}

		K_NOTHROW void SafeUnload()
		{
			*this = NULL;
		}

		K_NOTHROW kint SafeGetRef()
		{
			if (_ptr == NULL)
				return 0;
			else
			{
				_ptr->Load();
				return _ptr->Unload();
			}
		}

		K_NOTHROW void Swap(BasePtr& ptr)
		{
			BASETYPE* tmp = _ptr;
			_ptr = ptr._ptr;
			ptr._ptr = tmp;
		}
	};

	template <typename T, typename U>
	inline bool operator==(const BasePtr<T>& l, const BasePtr<U>& r)
	{
		return l.Ptr() == r.Ptr();
	}

	template <typename T>
	inline bool operator==(const BasePtr<T>& l, const T* r)
	{
		return l.Ptr() == r;
	}

	template <typename T>
	inline bool operator==(const T* l, const BasePtr<T>& r)
	{
		return l == r.Ptr();
	}

	template <typename T, typename U>
	inline bool operator!=(const BasePtr<T>& l, const BasePtr<U>& r)
	{
		return l.Ptr() != r.Ptr();
	}

	template <typename T>
	inline bool operator!=(const BasePtr<T>& l, const T* r)
	{
		return l.Ptr() != r;
	}

	template <typename T>
	inline bool operator!=(const T* l, const BasePtr<T>& r)
	{
		return l != r.Ptr();
	}

	/** COM 개체 스마트 포인터 */
	template <typename REFTYPE>
	class RefPtr
	{
	private:
		REFTYPE* _ptr;

	public:
		K_NOTHROW RefPtr() : _ptr(NULL)
		{
		}

		K_NOTHROW RefPtr(REFTYPE* ptr, bool addref = true)
			: _ptr(ptr)
		{
			if (ptr && addref)
				ptr->AddRef();
		}

		K_NOTHROW RefPtr(const RefPtr& o)
			: _ptr(o._ptr)
		{
			if (_ptr)
				_ptr->AddRef();
		}

		template <typename EITHERTYPE>
		K_NOTHROW RefPtr(const RefPtr<EITHERTYPE>& o)
			: _ptr(o._ptr)
		{
			if (_ptr)
				_ptr->AddRef();
		}

		K_NOTHROW ~RefPtr()
		{
			if (_ptr)
			{
				_ptr->Release();
				k_test(_ptr = NULL);
			}
		}

		K_NOTHROW RefPtr& operator=(REFTYPE* right)
		{
			REFTYPE* prev = _ptr;
			_ptr = right;
			if (right)
				right->AddRef();
			if (prev)
				prev->Release();
			return *this;
		}

		K_NOTHROW RefPtr& operator=(const RefPtr& right)
		{
			return *this = right._ptr;
		}

		template <typename EITHERTYPE>
		K_NOTHROW RefPtr& operator=(const RefPtr<EITHERTYPE>& right)
		{
			return *this = right._ptr;
		}

		template <typename EITHERTYPE>
		K_NOTHROW bool operator==(const RefPtr<EITHERTYPE>& right)
		{
			return _ptr == right._ptr;
		}

		K_NOTHROW REFTYPE* operator->() const
		{
			return _ptr;
		}

		K_NOTHROW operator REFTYPE*() const
		{
			return _ptr;
		}

		K_NOTHROW REFTYPE& operator*() const
		{
			return *_ptr;
		}

		K_NOTHROW REFTYPE** operator&()
		{
			return &_ptr;
		}

		K_NOTHROW bool operator!() const
		{
			return !_ptr;
		}

		K_NOTHROW operator bool() const
		{
			return _ptr != NULL;
		}

		K_NOTHROW REFTYPE** InitPtr()
		{
			*this = NULL;
			return &_ptr;
		}

		K_NOTHROW REFTYPE* Ptr() const
		{
			return _ptr;
		}

		K_NOTHROW friend bool TestPtr(const RefPtr& ptr)
		{
			return ptr._ptr != NULL;
		}

		K_NOTHROW void SafeRelease()
		{
			*this = NULL;
		}

		K_NOTHROW kint SafeGetRef()
		{
			if (_ptr == NULL)
				return 0;
			else
			{
				_ptr->Load();
				return _ptr->Unload();
			}
		}

		K_NOTHROW void Swap(RefPtr& ptr)
		{
			REFTYPE* tmp = _ptr;
			_ptr = ptr._ptr;
			ptr._ptr = tmp;
		}
	};

	template <typename T, typename U>
	inline bool operator==(const RefPtr<T>& l, const RefPtr<U>& r)
	{
		return l.Ptr() == r.Ptr();
	}

	template <typename T>
	inline bool operator==(const RefPtr<T>& l, const T* r)
	{
		return l.Ptr() == r;
	}

	template <typename T>
	inline bool operator==(const T* l, const RefPtr<T>& r)
	{
		return l == r.Ptr();
	}

	template <typename T, typename U>
	inline bool operator!=(const RefPtr<T>& l, const RefPtr<U>& r)
	{
		return l.Ptr() != r.Ptr();
	}

	template <typename T>
	inline bool operator!=(const RefPtr<T>& l, const T* r)
	{
		return l.Ptr() != r;
	}

	template <typename T>
	inline bool operator!=(const T* l, const RefPtr<T>& r)
	{
		return l != r.Ptr();
	}
}	// tpl























//////////////////////////////////////////////////////////////////////////
// boost application
namespace tpl
{
	// from boost
	namespace _boost
	{
		// foreach
		class foreach_iter
		{
		private:
			void* _myIt;
			bool  _runOnce;

		public:
			template <class Iter>
			foreach_iter(Iter it)
				: _runOnce(true)
			{
				_myIt = new Iter;
				*((Iter*)_myIt) = it;
			}

			virtual ~foreach_iter()
			{
				if (_myIt)
				{
					k_assert(0, "bad foreach iterator");
					k_exit(0);
				}
			}

			template <class Iter>
			Iter& increase(Iter it)
			{
				return ++(*((Iter*)_myIt));
			}

			template <class Iter>
			Iter& get(Iter it)
			{
				return *((Iter*)_myIt);
			}

			template <class Iter>
			bool all_done(Iter it)
			{
				bool ret = *((Iter*)_myIt) == it;
				if (ret)
					cleanup(it);
				return ret;
			}

			bool run_once()
			{
				bool ret = _runOnce;
				_runOnce = ret ? false : true;
				return ret;
			}

		private:
			template <class Iter>
			void cleanup(Iter it)
			{
				if (_myIt)
				{
					delete ((Iter*)_myIt);
					_myIt = 0;
				}
			}
		};
	}
}

#if _SB_CPP11_FOR_
#define BOOST_FOREACH(VAR, COL) \
	for (VAR : COL)
#else
#define BOOST_FOREACH(VAR, COL) \
	for (tpl::_boost::foreach_iter it((COL).begin()); !it.all_done((COL).end()); it.increase((COL).begin())) \
		for (VAR = *(it.get((COL).begin())); it.run_once();)
#endif

#define kForEach(VAR, COL) BOOST_FOREACH(VAR, COL)






















#endif	// __cplusplus

#if _MSC_VER
#pragma warning(pop)
#endif

#endif	// __SBTPL_H__
